const path = require('path')
const webpack = require('webpack')
const ProgressBarPlugin = require("progress-bar-webpack-plugin"); // 展示编译进度条
const FirendlyErrorePlugin = require("friendly-errors-webpack-plugin"); // 美化 webpack 的错误和警告
const TerserPlugin = require('terser-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const DefinePlugin = require('webpack').DefinePlugin
const ConsoleWebpackPlugin = require('./ConsoleWebpackPlugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const GenerateJsonPlugin = require("./custom-webpack-plugin");
const DemoWebpackPlugin = require("./demo-webpack-plugin");
const EslintWebpackPlugin = require('eslint-webpack-plugin');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const CopyWebpackPlugin = require("copy-webpack-plugin"); // 复制 public 文件夹到 dist 目录下
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const exec = require("child_process").exec;
const isDev = process.env.NODE_ENV === 'development'

function getGitLog() {
  let _cmd = `git log -5 --no-merges \
  --date=iso --pretty=format:'{"commit": "%h","author": "%aN <%aE>","date": "%ad","message": "%s"},' \
  $@ | \
  perl -pe 'BEGIN{print "["}; END{print "]\n"}' | \
  perl -pe 's/},]/}]/'`;
  return new Promise((resolve, reject) => {
    exec(_cmd, (error, stdout, stderr) => {
      if (error) {
        reject(stderr);
      } else {
        resolve(JSON.parse(stdout));
      }
    });
  });
}
const TIME_STAMP = +new Date();
const buidJson = {
  LAST_BUILD_TIME: TIME_STAMP
};
const createJson = function (_gitlog) {
  buidJson["GIT_LOG"] = _gitlog;

  return JSON.stringify(buidJson);
};
module.exports = {
  entry: {
    main: './src/index.js',
  },
  output: {
    // library: 'someLibName',
    // libraryTarget: 'umd',
    // filename: 'someLibName.js',
    // auxiliaryComment: 'Test Comment',
    filename: "[name].[chunkhash:8].js",
    path: path.resolve(__dirname, "dist"),
    clean: {
      keep: /dll/, // 保留 'ignored/dir' 下的静态资源
    },
    pathinfo: false
  },
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "src"),
      "utils": path.resolve(__dirname, "src/utils"),
      "public": path.resolve(__dirname, "public"),
    },
    extensions: [".tsx", ".ts", ".js"],
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        include: path.resolve(__dirname, "src"),
        use: [
          isDev ? "style-loader" : MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              importLoaders: 1,
              esModule: false,
              modules: {
                auto: true,
                localIdentName: "[name]__[local]--[contenthash:base64:8]",
              }
            },
          },
          "postcss-loader"
        ]
      },
      {
        test: /\.scss$/i,
        include: path.resolve(__dirname, "src"),
        use: [
          isDev ? "style-loader" : MiniCssExtractPlugin.loader,
          {
            loader: "css-loader",
            options: {
              esModule: false,
              importLoaders: 1,
              modules: {
                auto: true,
                localIdentName: "[name]__[local]--[contenthash:base64:8]",
              }
            },
          },
          "postcss-loader",
          {
            loader: "sass-loader",
            options: {
              additionalData: `@import "~@/variables.scss";` // 全局引入变量 非常好用
            }
          }
        ]
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif|svg)$/i,
        include: [path.resolve(__dirname, "public"), path.resolve(__dirname, "src")],
        type: 'asset',
        parser: {
          dataUrlCondition: {
            maxSize: 1024 * 10, // 10kb
          },
        },
        generator: {
          filename: 'images/[name][contenthash:8][ext]'
        },
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
      },
      {
        test: /\.js$/i,
        include: path.resolve(__dirname, "src"),
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-env"]
          }
        }
      },
      {
        test: /\.tsx?$/i,
        include: path.resolve(__dirname, "src"),
        use: [
          {
            loader: "ts-loader",
            options: {
              // transpileOnly: true, // 开启后 只转化不报错
            },
          }
        ],
        exclude: /node_modules/,
      },
    ]
  },
  externals: {
    // lodash: "lodash",
    // jquery: "jquery"
  },
  cache: {
    type: "filesystem",
  },
  optimization: {
    minimize: true,
    minimizer: [new TerserPlugin(), new CssMinimizerPlugin(),],
    splitChunks: {
      chunks: 'all',
    },
    // splitChunks: {
    //   chunks: 'async',
    //   minSize: 20000,
    //   minRemainingSize: 0,
    //   minChunks: 1,
    //   maxAsyncRequests: 30,
    //   maxInitialRequests: 30,
    //   enforceSizeThreshold: 50000,
    //   cacheGroups: {
    //     defaultVendors: {
    //       test: /[\\/]node_modules[\\/]/,
    //       priority: -10,
    //       reuseExistingChunk: true,
    //     },
    //     default: {
    //       minChunks: 2,
    //       priority: -20,
    //       reuseExistingChunk: true,
    //     },
    //   },
    // },
  },
  plugins: [
    new ProgressBarPlugin(),
    new FirendlyErrorePlugin(),
    // new webpack.DllReferencePlugin({
    //   context: __dirname,
    //   manifest: require("./dist/vendor-manifest.json")
    // }),
    new CopyWebpackPlugin({
      patterns: [{ from: path.resolve(__dirname, "./public") }]
    }),
   
    new webpack.DllReferencePlugin({
      context: __dirname,
      manifest: require("./dist/dll/manifest.json"),
      // scope: 'xyz',
      // sourceType: 'commonjs2',
    }),
    new AddAssetHtmlPlugin({
      filepath: path.resolve(__dirname, "dist/dll/jquery.js"),
      publicPath: "js/"
      // includeSourcemap: false
    }),
    new HtmlWebpackPlugin({
      title: "博客列表",
      template: './src/index.html',
      // hash: true
    }),
    // new AddAssetHtmlPlugin({
    //   outputPath: '../build/js',
    //   filepath: path.resolve(__dirname, "dist/vendor.dll.js"),
    // }),
    new DefinePlugin({
      BASE_URL: '"./"', // 需要外加'' 否则导出 会成为./ 不是字符串了
      API: '"api_test"',
      "process.env.API": JSON.stringify(process.env.API)
    }),
    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      reportFilename: 'report.html',
      openAnalyzer: false, // 不自动打开浏览器
    }),
    new ConsoleWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash:8].css',
    }),
    new GenerateJsonPlugin({
      filename: "version.json",
      fn: async function (compilation, cb) {
        let _gitlog = await getGitLog();
        cb(null, createJson(_gitlog));
      }
    }),
    new DemoWebpackPlugin(),
    // new EslintWebpackPlugin()
    new CompressionWebpackPlugin({
      filename: '[path][base].gz',
      algorithm: 'gzip',
      test: /\.(js|css|html|svg)$/,
      threshold: 10240,
      minRatio: 0.8
    })
  ]
}